//
//  HECircleChatManager.m
//  HealthFamily
//
//  Created by 吴欧 on 2021/2/25.
//  Copyright © 2021 honglutec. All rights reserved.
//

#import "HECircleChatManager.h"
#import "HEIMRoomMsgEntity.h"
#import "HEIMForward.h"
#import "HEAudioRecordManage.h"
#import "JPSuspensionEntrance.h"

@interface HECircleChatManager ()<HESocketManagerDelegate>
 
@property (nonatomic, strong) NSPointerArray *delegateList;

@property (nonatomic, strong) HEChatRoomModel *user; // 当前加入聊天室人员信息

@property (nonatomic, strong) NSOperationQueue *queue;

@property (nonatomic, strong) dispatch_semaphore_t semaphore;

@end

@implementation HECircleChatManager


#pragma mark - LifeCycle
+(instancetype)sharedManager {
    static dispatch_once_t onceToken;
    static HECircleChatManager *instance;
    dispatch_once(&onceToken, ^{
        instance = [[HECircleChatManager alloc] init];
        instance.delegateList = [NSPointerArray weakObjectsPointerArray];
        instance.currentUserList = @[].mutableCopy;
    });
    return instance;
}

- (instancetype)init {
    if (self = [super init]) {
        self.semaphore = dispatch_semaphore_create(0); //默认创建的信号为0
        self.queue = [[NSOperationQueue alloc] init];
        self.queue.maxConcurrentOperationCount = 1; // 串行队列
        [[HESocketManager sharedManager] addDelegate:self];
    }
    return self;
}

- (void)addDelegate:(id<HECircleChatManagerDelegate>)delegate {
    [self.delegateList addPointer: (__bridge void * _Nullable)delegate];
}

- (void)removeDelegate:(id<HECircleChatManagerDelegate>)delegate {
    [[self.delegateList allObjects] enumerateObjectsUsingBlock:^(id<HECircleChatManagerDelegate> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if (obj == delegate) {
            [self.delegateList removePointerAtIndex:idx];
            *stop = YES;
        }
    }];
}

- (void)removeAllDelegate {
    //先数组中添加一个NULL 才能清空数组
    [self.delegateList addPointer:NULL];
    [self.delegateList compact];
}

#pragma mark -
- (void)switchRoomVC:(HEChatRoomModel *)roomModel isFromChatPage:(BOOL)isFromChatPage  callback:(nonnull void (^)(HEIMCircleChatController * _Nonnull))callback{
    
    HEIMKitInfo *reciverInfo = [HEIMKitInfo new];
    reciverInfo.infoId = [NSString stringWithFormat:@"%ld", roomModel.roomId];
    reciverInfo.showName = roomModel.roomName;
    reciverInfo.avatarUrlString = roomModel.roomIcon;

    UserInfo *user = [UserManager sharedUserManager].curUserInfo;
    HEIMKitInfo *owner = [HEIMKitInfo new];
    owner.infoId = user.id;
    owner.showName = user.realname;
    owner.avatarUrlString = user.avatar;
    owner.avatarImage = IMAGE_NAMED(@"defualt_icon");
    
    [[HEIMKit sharedKit] registeUserInfos: @[reciverInfo, owner]];
    
//    HEIMCircleChatController *currentVC = (HEIMCircleChatController *)JPSEInstance.suspensionView.targetVC;
    HEIMCircleChatController *currentVC = (HEIMCircleChatController *)JPSEInstance.targetVC;

    if (roomModel.roomId == currentVC.roomId.integerValue) {
        if (isFromChatPage) {
            [currentVC.navigationController popToViewController:currentVC animated:YES];
        }else {
            [JPSuspensionEntrance.sharedInstance pushViewController: currentVC];
        }
    }else {
        
        // 切换其他房间时，设置离开房间状态
        [self leaveRoom];
        
        // 如果存在之前的房间，需要销毁掉
        if (currentVC != nil) {
            
            [self removeDelegate: (id<HECircleChatManagerDelegate>)currentVC];
 
            NSMutableArray *marr = [[NSMutableArray alloc] initWithArray:currentVC.navigationController.viewControllers];
            [marr removeObject:currentVC];
            currentVC.navigationController.viewControllers = marr;
        }
        
        // 创建新的房间
        HEIMCircleChatController *vc = [HEIMCircleChatController new];
        vc.roomId = [NSString stringWithFormat:@"%ld", roomModel.roomId];
        vc.isSuspension = YES;
        JPSEInstance.suspensionView = nil;
        [JPSuspensionEntrance.sharedInstance pushViewController: vc];
        currentVC = vc;
    }
    JPSEInstance.suspensionView.hidden = YES;
    callback(currentVC);
}

#pragma mark -

- (void)initOpration {
    
    // 监听聊天室列表数据
    SocketIOClient *socket = [HESocketManager sharedManager].socket;
    
    // 聊天室列表初始化指令
    KWeakSelf
    [[[HESocketManager sharedManager].socket emitWithAck:@"chatRoomList" with: @[]] timingOutAfter:0 callback:^(NSArray * _Nonnull data) {
        NSDictionary *msgDict = (NSDictionary *)[data objectAtIndex:0];
        DLog(@"%@", [msgDict mj_JSONString])
        DLog(@"实时获取聊天室列表初始化指令")
        
        HEObjectDataResponse *response = [HEObjectDataResponse mj_objectWithKeyValues:msgDict];
        NSArray <HEChatRoomModel *>*teams = [HEChatRoomModel mj_objectArrayWithKeyValuesArray: [response.data mj_JSONObject]];
        weakSelf.teams = teams;
        
        for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
            if ([delegate respondsToSelector:@selector(allTeams:)]) {
                [delegate allTeams: teams];
            }
        } 
    }];
    
}

- (void)chatRoomUpHandler:(NSDictionary *)msg {
    DLog(@"%@", [msg mj_JSONString])

    HEChatRoomModel *model = [HEChatRoomModel mj_objectWithKeyValues:msg];
    
    UserInfo *user = [UserManager sharedUserManager].curUserInfo;
    if (model.type == HETeamOperationTypeLeave && [user.id isEqualToString:model.userId]) {
        self.isInRoom = NO;
    }
     
    [self dealTeamUserOpratione: model];
    
    for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
        if ([delegate respondsToSelector:@selector(teamUserChangeInfo:)]) {
            [delegate teamUserChangeInfo: model];
        }
    }
}

- (void)chatRoomMsgHandler:(NSDictionary *)msg {
    DLog(@"%@", [msg mj_JSONString])

    HEIMRoomMsgEntity *model = [HEIMRoomMsgEntity mj_objectWithKeyValues: msg];
    
    HEIMInfoEntity *entitiy = [HEIMInfoEntity new];
    entitiy.from = model.usid;
    entitiy.from_id = model.usid;
    entitiy.to = [NSString stringWithFormat:@"%ld", model.roomId];
    entitiy.content = model.content;

    NSArray *meassageArr = [HEIMForward transformIMModel:@[entitiy]];

    for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
        if ([delegate respondsToSelector:@selector(onRecvMessages:)]) {
            [delegate onRecvMessages: meassageArr.firstObject];
        }
    }
}

- (void)chatRoomListUpHandler:(NSDictionary *)msg {
    DLog(@"%@", [msg mj_JSONString])

    NSNumber *type = (NSNumber *)msg[@"type"];
    HEChatRoomModel *room = [HEChatRoomModel mj_objectWithKeyValues:msg[@"data"]];

    if (type.integerValue == HETeamStatusTypeDelete) {
        for (int i = 0; i < self.teams.count; i++) {
            HEChatRoomModel *obj = self.teams[i];
            if (room.roomId == obj.roomId) {
                [self.teams removeObjectAtIndex:i];
                break;
            }
        }
    }else {
        [self.teams addObject:room];
    }
    
    for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
        if ([delegate respondsToSelector:@selector(allTeams:)]) {
            [delegate allTeams: self.teams];
        }
    }
}

// 处理所有聊天室用户加入、退出
- (void)dealTeamUserOpratione:(HEChatRoomModel *)model {
    // 找到当前所在的聊天室
    for (int i = 0; i < self.teams.count; i++) {
        HEChatRoomModel *team = self.teams[i];
        if (team.roomId == model.roomId) {
            team.roomNum = model.roomNum;
            team.KroomNumText = model.KroomNumText;
            team.users = model.avatarList;
            for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
                if ([delegate respondsToSelector:@selector(updateTeamInfo:index:)]) {
                    [delegate updateTeamInfo:team index: i];
                }
            }
            break;
        }
    }
}

// 加入聊天室
- (void)joinRoom:(HEChatRoomModel *)user callback:(nonnull void (^)(BOOL))callback{
    
    _user = user;
    
    KWeakSelf
    [[[HESocketManager sharedManager].socket emitWithAck:@"chatRoomJoin" with: @[[user mj_JSONString]]] timingOutAfter:0 callback:^(NSArray * _Nonnull data) {
        
        weakSelf.isInRoom = YES;
        NSDictionary *msgDict = (NSDictionary *)[data objectAtIndex:0];
        DLog(@"%@", [msgDict mj_JSONString])
        
        HEObjectDataResponse *response = [HEObjectDataResponse mj_objectWithKeyValues:msgDict];
        NSArray *users = [response.data mj_JSONObject];
        NSMutableArray *userList = @[].mutableCopy;
        for (NSDictionary *dict in users) {
            HEIMKitInfo *info = [HEIMKitInfo new];
            info.infoId = dict[@"userId"];
            info.avatarUrlString = dict[@"avatar"];
            info.showName = dict[@"nickname"];
            info.avatarImage = IMAGE_NAMED(@"defualt_icon");

            [userList addObject:info];
        }
        for (id<HECircleChatManagerDelegate> delegate in self.delegateList) {
            if ([delegate respondsToSelector:@selector(teamAllUsers:)]) {
                [delegate teamAllUsers: userList];
            }
        }
        callback(YES);
    }];
}

- (void)leaveRoom {
    
    self.isInRoom = NO;
    if (JPSEInstance.targetVC) {
        [self removeDelegate: (id<HECircleChatManagerDelegate>)JPSEInstance.targetVC];
    }
    
    HEChatRoomModel *luser = [HEChatRoomModel new];
    luser.roomId = _user.roomId;
    luser.userId = _user.userId;
    
    KWeakSelf
    [[[HESocketManager sharedManager].socket emitWithAck:@"chatRoomLeave" with: @[[luser mj_JSONString]]] timingOutAfter:0 callback:^(NSArray * _Nonnull data) {
        NSDictionary *msgDict = (NSDictionary *)[data objectAtIndex:0];
        DLog(@"%@", [msgDict mj_JSONString])
    }];
    _user = nil;
}

- (void)sendMessage:(HEIMMessageModel *)message callback:(nonnull void (^)(BOOL))callback {
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        DLog(@"sendddd  开始执行任务...")
        KWeakSelf
        [self sendIMMessage:message completion:^(BOOL success) {
            if (success) {
                message.deliveryState = HEIMMessageDeliveryStateDeliveried;
            }
            for (id<HECircleChatManagerDelegate> delegate in weakSelf.delegateList) {
                if ([delegate respondsToSelector:@selector(sendMessageCallback:)]) {
                    [delegate sendMessageCallback: message.message];
                }
            }
            callback(success);
            dispatch_semaphore_signal(self.semaphore); //这里请求成功信号量 +1 为1
        }];
        dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_FOREVER); //信号量减1，走到这里如果信号量为0，则不再执行下面的代码
    }];
    [_queue addOperation:op1];
}

#pragma mark - HESocketManagerDelegate
- (void)onErrorHandler {
    self.isInRoom = NO;
    dispatch_semaphore_signal(self.semaphore); //这里请求成功信号量 +1 为1
}

- (void)onDisConnectHandler {
    self.isInRoom = NO;
    dispatch_semaphore_signal(self.semaphore); //这里请求成功信号量 +1 为1
}

- (void)sendIMMessage:(HEIMMessageModel *)message completion:(void (^)(BOOL success))completion{
    
    switch (message.message.type) {
        case HEIMMessageTypeText:
        case HEIMMessageTypeAT:
        {
            HEIMInfoEntity *info = [self returnIMEntity:message];
            [self emit:[info mj_JSONObject] completion:^(BOOL success) {
                completion(success);
            }];
        }
            break;
        case HEIMMessageTypeAudio:
        {
            HEIMInfoEntity *info = [self returnIMEntity:message];
            NSURL *url = [NSURL fileURLWithPath:info.contentModel.content];
            
            [WOAFNetWorkingHandle batchUploadFileWithBaseURL:KServerUrl suffixUrl:Kbatch parameters:@{} name:nil filePaths: @[url] fileNames:nil mediaType:nil progress:^(int64_t bytesProgress, int64_t totalBytesProgress) {
                
            } success:^(id  _Nonnull responseObject) {
                HEUploadResponse *response = [HEUploadResponse mj_objectWithKeyValues:responseObject];
                
                if (response.success) {
                    info.contentModel.content = response.data.kSrc;
                    info.content = [info.contentModel mj_JSONString];
                    HEIMAudioObject *audio = (HEIMAudioObject *)message.message.messageObject;
                    audio.url = response.data.kSrc;
                    [self emit:[info mj_JSONObject] completion:^(BOOL success) {
                        completion(success);
                        // 上传语音成功后删除缓存语音文件
                        [[HEAudioRecordManage sharedManager] removeFileAtPath:url.path];
                    }];
                }else {
                    completion(false);
                }
            } failure:^(NSError * _Nonnull error) {
                completion(false);
                return;
            }];
        }
            break;
            
        case HEIMMessageTypeImage:
        {
            HEIMInfoEntity *info = [self returnIMEntity:message];
            
            NSMutableArray *arr = @[].mutableCopy;
            NSArray *urlPaths = [info.contentModel.content componentsSeparatedByString:@","];
            for (NSString *url in urlPaths) {
                [arr addObject:[NSURL fileURLWithPath:url]];
            }
            
            [WOAFNetWorkingHandle batchUploadFileWithBaseURL:KServerUrl suffixUrl:Kbatch parameters:@{} name:nil filePaths: arr fileNames:nil mediaType:nil progress:^(int64_t bytesProgress, int64_t totalBytesProgress) {
                
            } success:^(id  _Nonnull responseObject) {
                HEUploadResponse *response = [HEUploadResponse mj_objectWithKeyValues:responseObject];
                
                if (response.success) {
                    info.contentModel.content = response.data.kSrc;
                    info.content = [info.contentModel mj_JSONString];
                    [self emit:[info mj_JSONObject] completion:^(BOOL success) {
                        completion(success);
                    }];
                }else {
                    completion(false);
                }
            } failure:^(NSError * _Nonnull error) {
                completion(false);
                return;
            }];
        }
            break;
            
        case HEIMMessageTypeConsulReport:
        {
            HEIMInfoEntity *info = [self returnIMEntity:message];
            [self emit:[info mj_JSONObject] completion:^(BOOL success) {
                completion(success);
            }];
        }
            break;
        case HEIMMessageTypeInfoPage:
        case HEIMMessageTypeInfoVideo:
        {
            HEIMInfoEntity *info = [self returnIMEntity:message];
            [self emit:[info mj_JSONObject] completion:^(BOOL success) {
                completion(success);
            }];
        }
            break;
             
        default:
            completion(false);
            break;
    }
}

- (void)emit:(NSDictionary *)params completion:(void (^)(BOOL success))completion  {
    
    [[[HESocketManager sharedManager].socket emitWithAck: @"chatRoomSendMsg" with: @[[params mj_JSONString]]] timingOutAfter:0 callback:^(NSArray * _Nonnull data) {
        DLog(@"sendddd  发送成功...%@",[params mj_JSONString] )

        NSDictionary *msgDict = (NSDictionary *)[data objectAtIndex:0];
        HEResponse *response = [HEResponse mj_objectWithKeyValues: msgDict];
        completion(response.success);
    }];
}

- (HEIMInfoEntity *)returnIMEntity:(HEIMMessageModel *)message {
    UserInfo *user = [UserManager sharedUserManager].curUserInfo;
    
    NSString *name = [DYTools isBlankString:user.realname] ? user.nickname : user.realname;
    
    HEIMMessage *msg = message.message;
    HEIMInfoEntity *entitiy = [HEIMInfoEntity new];
    entitiy.from = msg.from;
    entitiy.from_id = msg.from;
    entitiy.to = msg.to;
//    entitiy.cmd = @"11";
    entitiy.create_date = [NSDate getNowTimeTimestamp];
//    entitiy.chatType = @"2";
    entitiy.msgType = message.message.modelType == HEIMUserModelTypeIM ? @"0" : @"1";
    
    switch (message.message.type) {
        case HEIMMessageTypeText:
        {
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = msg.text;
            content.type = HEIMMessageTypeText;
            content.nickname = name;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
        case HEIMMessageTypeAudio:
        {
            
            HEIMAudioObject *audio = (HEIMAudioObject *)msg.messageObject;
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = audio.url;
            content.type = HEIMMessageTypeAudio;
            content.nickname = name;
            content.seconds = audio.duration;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
            
        case HEIMMessageTypeImage:
        {
            
            HEIMImageObject *image = (HEIMImageObject *)msg.messageObject;
            
            NSMutableArray *arr = @[].mutableCopy;
            for (HEIMImageObject *item in image.imageArray) {
                [arr addObject:item.url.path];
            }
            
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = [arr componentsJoinedByString:@","];
            content.type = HEIMMessageTypeImage;
            content.nickname = name;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
            
        case HEIMMessageTypeConsulReport:
        {
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = msg.text;
            content.type = HEIMMessageTypeConsulReport;
            content.nickname = name;
            content.content = message.message.text;
            content.reportTitle = message.message.title;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
        case HEIMMessageTypeAT:
        {
            HEIMATObject *at = (HEIMATObject *)msg.messageObject;
            
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = msg.text;
            content.type = HEIMMessageTypeAT;
            content.nickname = name;
            content.atIds = at.atIds;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
            
        case HEIMMessageTypeInfoPage:
        case HEIMMessageTypeInfoVideo:
        {
            HEIMInfoPageObject *infoPage = (HEIMInfoPageObject *)msg.messageObject;
             
            HEIMInfoPageContentEntity *pageInfoEntity = [HEIMInfoPageContentEntity new];
            pageInfoEntity.id = infoPage.id;
            pageInfoEntity.voiceUrl = infoPage.voiceUrl;
            pageInfoEntity.icon = infoPage.iconUrlStr;
            pageInfoEntity.title = infoPage.title;
            pageInfoEntity.infoUrl = infoPage.infoUrl;
            pageInfoEntity.subTitle = infoPage.subTitle;
            
            HEIMInfoContentEntity *content = [HEIMInfoContentEntity new];
            content.actor = msg.actor;
            content.content = [pageInfoEntity mj_JSONString];
            content.type = message.message.type;
            content.nickname = name;
            entitiy.content = [content mj_JSONString];
            return entitiy;
        }
            break;
            
            
        default:
            break;
    }
    return nil;
}

- (void)closeAllRoom {
    [[JPSuspensionEntrance sharedInstance] removeSuspensionView];
    [[HECircleChatManager sharedManager] removeAllDelegate];
}

@end
